<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">

  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <title>老oa查询外挂</title>
  <link rel="stylesheet" crossorigin="anonymous"
    href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.1/css/bootstrap.min.css">
  <link rel="stylesheet" crossorigin="anonymous"
    href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.1/animate.min.css">

  <link rel="stylesheet" crossorigin="anonymous"
    href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.0/bootstrap-table.min.css">


  <link rel="stylesheet" crossorigin="anonymous"
    href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.0/themes/bootstrap-table/bootstrap-table.min.css">

  <style>
    .glassbga {
      /*渐变*/
      background: linear-gradient(to right bottom, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.2));
      ;
      border-radius: 1rem;
      box-shadow: 6px 6px 10px rgba(112, 112, 112, 0.2);
    }

    .glassbg {
      /*背景*/
      background: linear-gradient(to right top, #65dfc9, #6cdbeb);
      border-radius: 1rem;
    }

    .center {
      position: absolute;
      left: 50%;
      top: 10%;
      transform: translate(-50%, -50%);
    }

    [v-cloak] {
      display: none;
    }
  </style>
</head>


<body id="q-app" class="glassbg text-white  ">
  <!---设置-->
  <div class="  d-none  d-sm-flex   fixed-top justify-content-end ">
    <span @click="pd.shwoChange=!pd.shwoChange " class="btn "
      style="font-size:32px;  filter: grayscale(100%); ">⚙</span>
  </div>






  <!---上面的结果框val--->
  <div v-cloak class="container ">
    <div class="mt-2 row justify-content-center  ">
      <div class="w-100 mb-5   d-none d-md-block"><!---高度垫子 小设备隐藏--></div>
      <div>
        <h3>oa基础数据查询</h3>
      </div>

    </div>
  </div>



  <!---齿轮设置-->
  <transition v-cloak enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
    <div v-if="pd.shwoChange==0?false:true" class="container-md     glassbga  mt-4  mb-4   pt-3  pb-3">
      <div class=" row  align-items-center   justify-content-around  ">
        <div class="col-2  p-0 m-0 d-flex col-1 col-md-1 col-sm-1  justify-content-end  ">
          <label class="text-dark    mt-1       ">名字</label>
        </div>
        <div class="  p-0 m-0 col-6   col-md-4 col-sm-4   align-items-center  justify-content-start ">
          <input type="text" v-model="pd.searchName" class="  form-control" placeholder="请输入名字">
        </div>

        <div class="   d-flex col-auto   justify-content-start  ">
          <button @click="er.emit('查询' ) " class="btn shadow-lg btn-danger">查询</button>
        </div>


      </div>


    </div>

  </transition>



  <!--功能选择--->
  <transition v-cloak enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
    <div v-cloak v-if="pd.searchName" class="  container-md     glassbga  mt-4  mb-4   pt-3  pb-3  ">
      <div class="     justify-content-center  ">


        <ul class="nav nav-tabs   ">
          <li class="nav-item">
            <a class="nav-link shadow  bg-secondary  text-white  px-1 px-sm-3 px-lg-5 mx-1 mx-sm-2 mx-lg-1   "
              @click="pd.tabSele  = '基本信息' " :class="[{' active bg-info ': ('基本信息' == pd.tabSele )} ]">基本信息</a>
          </li>
          <li class="nav-item" id="prac">
            <a class="nav-link shadow   bg-secondary text-white  px-1 px-sm-3 px-lg-5 mx-1 mx-sm-2 mx-lg-2"
              @click="pd.tabSele  = '请假' " :class="[{' active bg-info ': ('请假' == pd.tabSele )} ]">请假</a>
          </li>
          <li class="nav-item" id="test">
            <a class="nav-link shadow   bg-secondary  text-white px-1 px-lg-3 px-lg-5 mx-1 mx-sm-2 mx-lg-2"
              @click="pd.tabSele  = '公出' " :class="[{' active bg-info ': ('公出' == pd.tabSele )} ]">公出</a>
          </li>
          <li class="nav-item" id="test">
            <a class="nav-link shadow   bg-secondary  text-white  px-1 px-sm-3 px-lg-5 mx-1 mx-sm-2 mx-lg-2"
              @click="pd.tabSele  = '补考勤' " :class="[{' active bg-info ': ('补考勤' == pd.tabSele )} ]">补考勤</a>
          </li>
          <li class="nav-item" id="test">
            <a class="nav-link shadow   bg-secondary  text-white  px-1 px-sm-3 px-lg-5 mx-1 mx-sm-2 mx-lg-2"
              @click="pd.tabSele  = '考勤' " :class="[{' active bg-info ': ('考勤' == pd.tabSele )} ]">考勤</a>
          </li>
        </ul>
        <div :class="[{' d-none ': ! (  '基本信息' == pd.tabSele )} ]">
          <table class="  bg-white" id="table"></table>
        </div>
        <div :class="[{' d-none ': ! (  '请假' == pd.tabSele )} ]">
          <table class="  bg-white" id="请假"></table>
        </div>
        <div :class="[{' d-none ': ! (  '公出' == pd.tabSele )} ]">
          <table class="  bg-white" id="公出"></table>
        </div>
        <div :class="[{' d-none ': ! (  '补考勤' == pd.tabSele )} ]">
          <table class="  bg-white" id="补考勤"></table>
        </div>
        <div :class="[{' d-none ': ! (  '考勤' == pd.tabSele )} ]">
          <table class="  bg-white" id="考勤"></table>
        </div>
      </div>

    </div>
  </transition>




  <!---上面的结果框val--->
  <div v-cloak class="container-sm ">

    <div class="  row justify-content-center  ">


    </div>
  </div>



  <!---info提示信息--->
  <transition v-cloak mode="out-in" enter-active-class="animated pulse" leave-active-class="animated bounceOutRight">
    <div class=" container-sm  fixed-top    " style="z-index: 1083 ;" v-for="site in pd.info_list">
      <div class="alert  alert-warning alert-dismissible fade show" role="alert">
        <strong>{{site.type}}</strong>{{ site.info }}
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
    </div>
  </transition>
  <!---遮罩1024--->
  <div v-cloak v-if="pd.sp==0?false:true" @click="er.emit('遮罩',0) " style="z-index: 1081  ;"
    class=" modal-backdrop show ">

  </div>
  <!---载入动画--->
  <transition v-cloak leave-active-class="animated fadeOut">
    <div v-if="pd.sp==0?false:true"
      class="center w-100 mt-5   row d-flex     align-items-center  justify-content-center  " style="z-index: 1082  ;">
      <div class="spinner-border   "></div>
    </div>
  </transition>




  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.47/vue.global.prod.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.10.0/lodash.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/EventEmitter/5.2.8/EventEmitter.min.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.4.0/axios.min.js"></script>


  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.0/bootstrap-table.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.0/bootstrap-table-vue.min.js"></script>
  <script
    src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.0/locale/bootstrap-table-zh-CN.min.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/URI.js/1.19.11/URI.min.js"></script>


  <script src="./danfo1.1.2.js"></script>
  <!---bootstraptable行合并  onLoadSuccess  mergeCells-->

  <script>
    const er = new EventEmitter //事件线
    const { onMounted, emits, createApp, ref, watch, computed } = Vue

    const gd = {};//全局数据 解决调用引用问题
    gd.group = 'oldoa' //功能应用分组
    gd.reg = {} //组成类到全局调用
    gd.storage = {
      //本地浏览器 存取组件
      set(key, value, area) {
        key = area ? area + ':' + key : key;//分区域分区组
        key = gd.group + '.' + key;//分组
        localStorage.setItem(key, JSON.stringify(value));
      },
      get(key, area) {
        key = area ? area + ':' + key : key;//分区域分区组
        key = gd.group + '.' + key;//分组
        return JSON.parse(localStorage.getItem(key));
      },
      remove(key, area) {
        key = area ? area + ':' + key : key;//分区域分区组
        key = gd.group + '.' + key;//分组
        localStorage.removeItem(key);
      },
    }
    gd.pd = ref({});//page data 页面元素引用"数据"
    //const pd = ref({ "load": [] }); //特殊变量，页面数据
    const pvs = gd.pd.value; //变量代理访问
    class pgui {
      /* 界面控制类 初始化界面默认值 */
      constructor(arg) {
        //初始（值）
        //----页面参数
        pvs.url = new URI() //获取去 type，pid ，默认访问本站，数据加载主站
        var dc = pvs.url.query(true);//参数
        //--界面值
        gd.reg.ui = this//全局资源
        pvs.sp = 0; //遮罩路由 (0.无，1.名单，2.登入 ,3.管理)
        pvs.info_list = []//交互提示 {info:"2",type:"2"}
        pvs.rawDat = {}

        pvs.searchName = dc['name'] ? dc['name'] : gd.storage.get('searchName') ? gd.storage.get('searchName') : '';//'默认查询名
        //--存储默认值
        pvs.shwoChange = gd.storage.get('shwoChange') ? gd.storage.get('shwoChange') : 1;//设置显示
        pvs.tabSele = gd.storage.get('tabSele') ? gd.storage.get('tabSele') : '基本信息';//'默认路径'
        pvs.rowBase = []  //基本信息
        //初始效果

        this.init();
      }

      init() {
        //初始（设置）
        //绑定事件

        er.on('遮罩', this.spto)
        er.on('查询', this.toSearch)
        er.on('展示补考勤', this.tab补考勤)
        er.on('展示请假', this.tab请假)
        er.on('展示公出', this.tab公出)
        //er.on('获取音标', this.toGetPh) //获取音标

      }
      toSearch() {
        //查询数据
        const ui = gd.reg.ui
        const se = gd.reg.se
        gd.storage.set('searchName', pvs.searchName)
        if (!pvs.searchName) { return }

        pvs.rawDat = {}
        //动画效果
        ui.loginLoading(1)
        ui.spto(1) //loading 
        er.emit('se.user')
        er.emit('se.kq')
      }
      tab请假() {
        const ui = gd.reg.ui
        /*
        AUTHOR: "11ed-a9b8-191b765e-a8b2-a36392a02a45"
ITEM_APPLICANT: "蔡金凯"
开始事件: "2023-05-25 16:46:00"
模块: "请假申请"
理由: "测试"
结束事件: "2023-05-25 16:46:00"
*/
        var rows = pvs.rawDat.TLK_APPLY_LEAVE//考勤表
        if (pvs.rawDat.T_DEPARTMENT && pvs.rawDat.T_DEPARTMENT.length > 0) {


        }
        var columns = [{
          field: '开始时间',
          title: '开始时间'
        }, {
          sortable: true,
          field: '结束时间',
          title: '结束时间'
        }
          , {
          sortable: true,
          field: '公出城市',
          title: '公出城市'
        }
          , {
          sortable: true,
          field: '理由',
          title: '理由'
        }
        ]

        ui.showTab('#请假', columns, rows)

      }
      tab公出() {
        const ui = gd.reg.ui
        //
        var rows = pvs.rawDat.TLK_BUSINESS_PUBLIC_TRIP//考勤表
        if (pvs.rawDat.T_DEPARTMENT && pvs.rawDat.T_DEPARTMENT.length > 0) {


        }
        var columns = [{
          field: 'ITEM_TRAVEL_OT',
          title: '起始时间'
        }, {
          sortable: true,
          field: 'ITEM_TRAVEL_ST',
          title: '结束时间'
        }
          , {
          sortable: true,
          field: '公出城市',
          title: '公出城市'
        }
          , {
          sortable: true,
          field: '理由',
          title: '理由'
        }
        ]

        ui.showTab('#公出', columns, rows)

      }
      tab补考勤() {
        //跳转、翻页
        const ui = gd.reg.ui

        //
        var rows = pvs.rawDat.TLK_ATTENDANCEDETAIL//考勤表
        if (pvs.rawDat.T_DEPARTMENT && pvs.rawDat.T_DEPARTMENT.length > 0) {

        }
        var columns = [{
          field: 'AUTHOR',
          title: '用户id'
        }, {
          sortable: true,
          field: 'ITEM_ATTDATE',
          title: '补卡时间'


        }]

        ui.showTab('#补考勤', columns, rows)
      }



      showTab(eid, col, dat) {
        // 生成和销毁表格
        if ($(eid).bootstrapTable("getOptions").cache == true) {
          $(eid).bootstrapTable('destroy');
          //return
        }
        $(eid).bootstrapTable({
          data: dat,        // 表格数据来源
          classes: "table table-bordered table-striped", //table-striped表示隔行变色
          theadClasses: 'thead',
          sortStable: true,
          search: true,                      //是否显示表格搜索
          striped: true,                      //是否显示行间隔色
          //showRefresh: true,//刷新按钮
          pageNumber: 1, //初始化加载第一页
          pagination: true,//是否分页
          sidePagination: 'client',//server:服务器端分页|client：前端分页
          pageSize: 10,//单页记录数
          pageList: [10],
          columns: col
        });



      }

      loginLoading(n) {
        //登入中效果
        pvs.loginLoding = n
      }
      spto(n) {
        //遮罩和二级界面
        /*切换界面*/
        pvs.sp = n
      }



      showInfo(info, type = '') {
        //结果提示信息 （数据驱动）
        //添加数据，来添加提示
        pvs.info_list.push({ "info": info, "type": type })
        //缺少动效
        setTimeout(function () { pvs.info_list.splice(0, 1); }, 4000);
      }


      watchPg(newValue, oldValue) {
        //watch
        //console.log('gd pagedata 被修改')
        //console.log('gd pagedata 被修改\n', newValue, '\n', oldValue)
      }

    }

    class select {
      /* 界面控制类 初始化界面默认值 */
      constructor(arg) {
        //初始（值）

        //--界面值
        gd.reg.se = this//全局资源

        pvs.rawDat = {}

        //初始效果
        this.hd = { //请求头
          mode: 'cors',
          cache: 'no-cache',
          "headers": {
            'Content-Type': 'application/json'
          }
        }
        this.keys = [] //完成清单
        //数据配置
        this.dcfg = {
          "oa/T_USER": {
            "@column": "ID,NAME,DEFAULTDEPARTMENT",
            "NAME": '蔡金凯',
            "@limit": 1
          }
        }
        this.knum = _.keys(this.dcfg).length; //完成清单

        this.init();
      }

      init() {
        //初始（设置）
        //绑定事件
        er.on('se.user', this.seUser)

        er.on('se.kq', this.seKq)

        er.on('展示考勤', this.tab考勤)

        er.on('展示用户', this.tabBase)


      }



 

      seKq() {
        const ui = gd.reg.ui
        const se = gd.reg.se
        //查询考勤
        var vn = {
          "kq/USERINFO": {
            "@column": "BADGENUMBER.用户id,NAME,USERID.考勤id,DEFAULTDEPTID",
            "NAME": pvs.searchName,
            "@limit": 1
          },
          "kq/CHECKINOUT": {
            "@column": "USERID.考勤id,CHECKTIME",
            "USERID|": "kq/USERINFO.考勤id"
            , 'CHECKTIME&': ">" + moment().subtract(2, 'month').format('YYYY-MM') + '-01'
            , "@order": "-CHECKTIME"
          }
        }
 
        var url = `//${pvs.url.hostname()}:2028/jsonapi/get`;
        // //发送
        se.se2(vn, url, 'kq', '考勤信息', ['展示考勤'])


      }

      seUser() {
        const ui = gd.reg.ui
        const se = gd.reg.se

        //获取数据，发送请求
        var url = `//${pvs.url.hostname()}:2028/jsonapi/get`;

        // //发送
        //return

        var vn = {
          "oa/T_USER": {
            "@column": "ID,NAME,DEFAULTDEPARTMENT.部门id,TELEPHONE.手机",
            "NAME": pvs.searchName,
            "@limit": 1
          },
          "oa/T_DEPARTMENT": {//部门
            "@column": "ID.部门id,NAME.部门",
            "ID|": "oa/T_USER.部门id",
            "@limit": 1
          },
          "oa/TLK_ATTENDANCEDETAIL": {//补考勤
            "AUTHOR|": "oa/T_USER.ID"
            , "ITEM_ATTDATE&": ">" + moment().subtract(2, 'month').format('YYYY-MM') + '-01'
            , "@order": "-CREATED"
            , "@column": "ITEM_ATTDATE, FORMNAME,AUTHOR,CREATED"
          },

          "oa/TLK_APPLY_LEAVE": {//请假
            "AUTHOR|": "oa/T_USER.ID"
            , "ITEM_LEAVE_T&": ">" + moment().subtract(2, 'month').format('YYYY-MM') + '-01'
            , "@order": "-CREATED"
            , "@column": "AUTHOR, ITEM_START_T.开始时间,ITEM_LEAVE_T.结束时间,ITEM_LEAVE_R.理由,ITEM_TITLE.模块,ITEM_APPLICANT,CREATED"
          }
          ,
          "oa/TLK_BUSINESS_PUBLIC_TRIP": {//公出
            "AUTHOR|": "oa/T_USER.ID"
            , "ITEM_TRAVEL_OT&": ">" + moment().subtract(2, 'month').format('YYYY-MM') + '-01'
            , "@order": "-CREATED"
            , "@column": "AUTHOR,ITEM_TRAVEL_ST,ITEM_TRAVEL_OT,ITEM_TRAVEL_R.理由, ITEM_TRAVEL_CITY.公出城市, FORMNAME.模块,STATELABELINFO,CREATED"
            , "#url": "http://127.0.0.1:2028/jsonapi/get"

          }
        }
        //获取数据，发送请求
        se.se2(vn, url, 'oa', '查询OA', ['展示用户', '展示请假', '展示公出', '展示补考勤'])
      }
      tabBase() {
        //跳转、翻页
        const ui = gd.reg.ui
        var 用户表 = new dfd.DataFrame(pvs.rawDat['oa/T_USER'])
        var 部门表 = new dfd.DataFrame(pvs.rawDat['oa/T_DEPARTMENT'])
        var 请假表 = new dfd.DataFrame(pvs.rawDat['oa/TLK_APPLY_LEAVE'])
        var 公出表 = new dfd.DataFrame(pvs.rawDat['oa/TLK_BUSINESS_PUBLIC_TRIP'])
        var 补考勤表 = new dfd.DataFrame(pvs.rawDat['oa/TLK_ATTENDANCEDETAIL'])


        //----
        用户表.print()
        部门表.print()
        请假表.print()
        公出表.print()
        补考勤表.print()
        //
        var 用户表v2 = dfd.merge({ "left": 用户表, "right": 部门表, "on": ["部门id"], how: "left" })
        用户表v2.print()

        const rows = dfd.toJSON(用户表v2)
        var columns = [{
          field: 'ID',
          title: '用户id'
        }, {
          sortable: true,
          field: 'NAME',
          title: '用户名'


        }, {
          field: '部门id',
          title: '部门id'
        }
          , {
          field: '部门',
          title: '部门'
        } , {
          field: '手机',
          title: '手机'
        }]

        ui.showTab('#table', columns, rows)
      }
      tab考勤() {
        //跳转、翻页
        const ui = gd.reg.ui
        
        var 考勤用户 = new dfd.DataFrame(pvs.rawDat['kq/USERINFO'])
        var 考勤记录 = new dfd.DataFrame(pvs.rawDat['kq/CHECKINOUT'])
   
        //
        var 考勤记录v2 = dfd.merge({ "left": 考勤记录, "right": 考勤用户, "on": ["考勤id"], how: "left" })
        考勤记录v2.print()

        const rows = dfd.toJSON(考勤记录v2)

        var columns = [{
          field: 'NAME',
          title: '用户'
        }, {
          sortable: true,
          field: 'CHECKTIME',
          title: '打卡时间'


        }]

        ui.showTab('#考勤', columns, rows)
      }

      se2(vn, url, name, info, next = '') {
        //单发送请求
        const se = gd.reg.se

        axios.post(url + '?' + name, vn, se.hd)
          .then(dat => {
            se.binding2(dat, name, info, next)
          })
          .catch(err => {
            se.getErr(err, name, info)
          })
      }

      binding2(dat, name, info, next = '') {
        //数据收集挂在到dat
        const ui = gd.reg.ui
        const se = gd.reg.se
        //数据挂在到dat
        //console.log('binding==', name, info)
        ui.loginLoading(0)
        ui.spto(0)
        if (dat.data['@code'] < 300) {
          //数据让如rawDat中
          ui.showInfo(dat.data['@msg'], info)
          //读取数据到 pvs
          var number = 0
          _.forEach(dat.data, function (value, key) {
            if (key.substr(0, 1) == '@') { return }
            pvs.rawDat[key] = dat.data[key]
            number = number + dat.data[key].length//行数
            if (dat.data[key].length > 0) {
              console.log(key + '==', dat.data[key].length, dat.data[key][0])
            } else {
              console.log(key, info, '无上数据')
            }
          });
          console.log(name + '加载', number, '行')
          ////下一步事件
          if (_.isString(next)) { er.emit(next) }
          //下一批事件
          if (_.isArray(next)) { _.map(next, (n) => { er.emit(n) }) }
        } else {
          ui.showInfo('出现错误', info)
          console.log('出现错误', info + '==', dat)
        }
      }

      getErr(error, naem, info) {
        //请求错误处理
        const ui = gd.reg.ui
        const se = gd.reg.se
        console.log('Error:', error, naem);
        ui.loginLoading(0) //loading 
        ui.spto(0) //loading  
        ui.showInfo('无法加载到数据，刷新重试', info) //loading  
      }


    }

    //----------开始
    let appdat = {
      setup() {
        const oui = new pgui(); //界面更改"方法"
        const se = new select(); //界面更改"方法"
        //const ocls = new cls(12);//默认选择
        //---放入全局解决this问题
        //gd.ocls = ocls; //抽奖类
        //gd.oin = oin; //通信逻辑
        gd.oui = oui; //ui界面

        watch(gd.pd, oui.watchPg, { deep: true });
        //pvs.opList = computed(() => oui.showOp('', '')); //二次计算pvs.opList
        //------

        //onMounted(() => ocls.bindEvt()); //窗口大小变动事件
        //onMounted(() => oui.remount()); //已经登入刷新处理
        onMounted(() => oui.toSearch(0)); //已经登入刷新处理
        //--变量关联到html的映射 js访问要加.value
        return { er, "pd": gd.pd, "ref_login_manage": gd.pd.refManageEmt, }
      }
    }
    const app = createApp(appdat)
    //app.use(Quasar) //vue的ui
    app.mount('#q-app')
  </script>



</body>

</html>